package com.smart.community.property.controller;

import java.util.List;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.property.service.DashboardService;
import com.smart.community.property.vo.DashboardBillingStandardVO;
import com.smart.community.property.vo.DashboardDataVO;
import com.smart.community.property.vo.DashboardInspectionVO;
import com.smart.community.property.vo.DashboardKpiVO;
import com.smart.community.property.vo.DashboardTrendVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

/**
 * 物业驾驶舱Controller
 * 提供驾驶舱页面所需的所有数据接口
 * 
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2025-01-30
 */
@Slf4j
@RestController
@RequestMapping("/property/dashboard")
@Tag(name = "物业驾驶舱", description = "物业驾驶舱相关接口")
@Validated
public class DashboardController {

    @Autowired
    private DashboardService dashboardService;

    /**
     * 获取驾驶舱完整数据
     * 
     * @param propertyCompanyId 物业公司ID
     * @return 驾驶舱完整数据
     * @throws Exception 统一异常
     */
    @GetMapping("/data/{propertyCompanyId}")
    @Operation(summary = "获取驾驶舱完整数据", description = "根据物业公司ID获取驾驶舱页面的完整数据")
    public Result<DashboardDataVO> getDashboardData(
            @Parameter(description = "物业公司ID") 
            @PathVariable @NotNull(message = "物业公司ID不能为空") 
            @Min(value = 1, message = "物业公司ID必须大于0") Long propertyCompanyId) throws Exception {
        log.info("获取驾驶舱完整数据，物业公司ID：{}", propertyCompanyId);
        
        // 验证用户权限
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("用户未登录，无法获取驾驶舱数据");
            return Result.error("用户未登录，请先登录");
        }
        
        if (!dashboardService.hasPropertyCompanyPermission(userId, propertyCompanyId)) {
            log.warn("用户无权限访问该物业公司数据，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
            return Result.error("您不是物业公司人员，无查看权限");
        }
        
        DashboardDataVO dashboardData = dashboardService.getDashboardData(propertyCompanyId);
        if (dashboardData == null) {
            log.warn("获取驾驶舱数据为空，物业公司ID：{}", propertyCompanyId);
            return Result.error("获取驾驶舱数据失败，数据为空");
        }
        
        log.info("获取驾驶舱完整数据成功，物业公司ID：{}，数据项数：{}", propertyCompanyId, 
                (dashboardData.getKpiData() != null ? 1 : 0) + 
                (dashboardData.getTrendData() != null ? 1 : 0) + 
                (dashboardData.getInspectionData() != null ? 1 : 0) + 
                (dashboardData.getBillingStandardData() != null ? dashboardData.getBillingStandardData().size() : 0));
        return Result.success(dashboardData);
    }

    /**
     * 获取KPI指标数据
     * 
     * @param propertyCompanyId 物业公司ID
     * @return KPI指标数据
     * @throws Exception 统一异常
     */
    @GetMapping("/kpi/{propertyCompanyId}")
    @Operation(summary = "获取KPI指标数据", description = "获取今日物业费收入、维修工单等KPI指标")
    public Result<DashboardKpiVO> getKpiData(
            @Parameter(description = "物业公司ID") 
            @PathVariable @NotNull(message = "物业公司ID不能为空") 
            @Min(value = 1, message = "物业公司ID必须大于0") Long propertyCompanyId) throws Exception {
        log.info("获取KPI指标数据，物业公司ID：{}", propertyCompanyId);
        
        // 验证用户权限
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("用户未登录，无法获取KPI数据");
            return Result.error("用户未登录，请先登录");
        }
        
        if (!dashboardService.hasPropertyCompanyPermission(userId, propertyCompanyId)) {
            log.warn("用户无权限访问该物业公司数据，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
            return Result.error("您不是物业公司人员，无查看权限");
        }
        
        DashboardKpiVO kpiData = dashboardService.getKpiData(propertyCompanyId);
        if (kpiData == null) {
            log.warn("获取KPI数据为空，物业公司ID：{}", propertyCompanyId);
            return Result.error("获取KPI数据失败，数据为空");
        }
        
        log.info("获取KPI指标数据成功，物业公司ID：{}，今日收入：{}，维修工单：{}", 
                propertyCompanyId, kpiData.getTodayIncome(), kpiData.getTodayRepairOrders());
        return Result.success(kpiData);
    }

    /**
     * 获取年度收费趋势数据
     * 
     * @param propertyCompanyId 物业公司ID
     * @param months 统计月数，默认12个月
     * @return 趋势数据
     * @throws Exception 统一异常
     */
    @GetMapping("/trend/{propertyCompanyId}")
    @Operation(summary = "获取年度收费趋势数据", description = "获取近N个月的收费趋势数据")
    public Result<DashboardTrendVO> getTrendData(
            @Parameter(description = "物业公司ID") 
            @PathVariable @NotNull(message = "物业公司ID不能为空") 
            @Min(value = 1, message = "物业公司ID必须大于0") Long propertyCompanyId,
            @Parameter(description = "统计月数") 
            @RequestParam(defaultValue = "12") 
            @Min(value = 1, message = "统计月数必须大于0") Integer months) throws Exception {
        log.info("获取年度收费趋势数据，物业公司ID：{}，统计月数：{}", propertyCompanyId, months);
        
        // 验证用户权限
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("用户未登录，无法获取趋势数据");
            return Result.error("用户未登录，请先登录");
        }
        
        if (!dashboardService.hasPropertyCompanyPermission(userId, propertyCompanyId)) {
            log.warn("用户无权限访问该物业公司数据，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
            return Result.error("您不是物业公司人员，无查看权限");
        }
        
        DashboardTrendVO trendData = dashboardService.getTrendData(propertyCompanyId, months);
        if (trendData == null) {
            log.warn("获取趋势数据为空，物业公司ID：{}", propertyCompanyId);
            return Result.error("获取趋势数据失败，数据为空");
        }
        
        log.info("获取年度收费趋势数据成功，物业公司ID：{}，数据点数量：{}", 
                propertyCompanyId, trendData.getDates() != null ? trendData.getDates().size() : 0);
        return Result.success(trendData);
    }

    /**
     * 获取设备安全检查数据
     * 
     * @param propertyCompanyId 物业公司ID
     * @return 安全检查数据
     * @throws Exception 统一异常
     */
    @GetMapping("/inspection/{propertyCompanyId}")
    @Operation(summary = "获取设备安全检查数据", description = "获取设备安全检查统计和详细记录")
    public Result<DashboardInspectionVO> getInspectionData(
            @Parameter(description = "物业公司ID") 
            @PathVariable @NotNull(message = "物业公司ID不能为空") 
            @Min(value = 1, message = "物业公司ID必须大于0") Long propertyCompanyId) throws Exception {
        log.info("获取设备安全检查数据，物业公司ID：{}", propertyCompanyId);
        
        // 验证用户权限
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("用户未登录，无法获取安全检查数据");
            return Result.error("用户未登录，请先登录");
        }
        
        if (!dashboardService.hasPropertyCompanyPermission(userId, propertyCompanyId)) {
            log.warn("用户无权限访问该物业公司数据，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
            return Result.error("您不是物业公司人员，无查看权限");
        }
        
        DashboardInspectionVO inspectionData = dashboardService.getInspectionData(propertyCompanyId);
        if (inspectionData == null) {
            log.warn("获取安全检查数据为空，物业公司ID：{}", propertyCompanyId);
            return Result.error("获取安全检查数据失败，数据为空");
        }
        
        log.info("获取设备安全检查数据成功，物业公司ID：{}，今日检查：{}项，合格率：{}%", 
                propertyCompanyId, inspectionData.getTodayInspections(), inspectionData.getTodayPassRate());
        return Result.success(inspectionData);
    }

    /**
     * 获取收费标准公示数据
     * 
     * @param propertyCompanyId 物业公司ID
     * @return 收费标准数据
     * @throws Exception 统一异常
     */
    @GetMapping("/billing-standard/{propertyCompanyId}")
    @Operation(summary = "获取收费标准公示数据", description = "获取当前物业公司的计费标准公示")
    public Result<List<DashboardBillingStandardVO>> getBillingStandardData(
            @Parameter(description = "物业公司ID") 
            @PathVariable @NotNull(message = "物业公司ID不能为空") 
            @Min(value = 1, message = "物业公司ID必须大于0") Long propertyCompanyId) throws Exception {
        log.info("获取收费标准公示数据，物业公司ID：{}", propertyCompanyId);
        
        // 验证用户权限
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("用户未登录，无法获取收费标准数据");
            return Result.error("用户未登录，请先登录");
        }
        
        if (!dashboardService.hasPropertyCompanyPermission(userId, propertyCompanyId)) {
            log.warn("用户无权限访问该物业公司数据，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
            return Result.error("您不是物业公司人员，无查看权限");
        }
        
        List<DashboardBillingStandardVO> billingStandardData = dashboardService.getBillingStandardData(propertyCompanyId);
        if (billingStandardData == null) {
            log.warn("获取收费标准数据为空，物业公司ID：{}", propertyCompanyId);
            return Result.error("获取收费标准数据失败，数据为空");
        }
        
        log.info("获取收费标准公示数据成功，物业公司ID：{}，收费标准数量：{}", 
                propertyCompanyId, billingStandardData.size());
        return Result.success(billingStandardData);
    }

    /**
     * 检查用户是否有物业公司权限
     * 
     * @return 是否有权限
     * @throws Exception 统一异常
     */
    @GetMapping("/check-permission")
    @Operation(summary = "检查用户物业公司权限", description = "检查当前用户是否有物业公司权限")
    public Result<Boolean> checkPropertyCompanyPermission() throws Exception {
        log.info("检查用户物业公司权限");
        
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("用户未登录，无法检查权限");
            return Result.error("用户未登录，请先登录");
        }
        
        boolean hasPermission = dashboardService.hasAnyPropertyCompanyPermission(userId);
        
        log.info("检查用户物业公司权限完成，用户ID：{}，有权限：{}", userId, hasPermission);
        return Result.success(hasPermission);
    }
}
